package wechat.util;

import java.time.Duration;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

public class RedisUtil {
	
	private static RedisUtil redisUtil;
	
	private static Configure INS = Configure.getInstans();
	
	private static final String SentinelsURL = INS.getValue("sentinel.urls") ;
	private static final String RedisMaster = INS.getValue("redis.master") ;
	private static final String RedisPassword = INS.getValue("redis.password");
	
	private static final String MaxTotal = INS.getValue("redis.maxTotal") ;
	private static final String MaxIdle = INS.getValue("redis.maxIdle") ;
	private static final String MaxWait = INS.getValue("redis.maxWait");
	private static final String MinEvictableIdle = INS.getValue("redis.minEvictableIdle");
	private static final String NumTestsPerEvictionRun = INS.getValue("redis.numTestsPerEvictionRun");
	private static final String TimeBetweenEvictionRunsMillis = INS.getValue("redis.timeBetweenEvictionRunsMillis");
	private static final String BlockWhenExhausted = INS.getValue("redis.blockWhenExhausted");

	
	private JedisSentinelPool sentinelPool;
	
	private RedisUtil() {
		//init();
	}

	public static RedisUtil getInstans() {
		if (redisUtil == null) {
			synchronized (RedisUtil.class) {
				if (redisUtil == null) {
					redisUtil = new RedisUtil();
				}
			}
		}
		return redisUtil;
	}
	
	private void init(){
		String[] url = SentinelsURL.split(",");
		
		Set<String> sentinels = new HashSet<String>();
		for (int i = 0; i < url.length; i++) {
			sentinels.add(url[i]);
		}
		
		GenericObjectPoolConfig<Jedis> poolConfig = new GenericObjectPoolConfig<Jedis>();
		poolConfig.setMaxTotal(Integer.valueOf(MaxTotal));
		poolConfig.setMaxIdle(Integer.valueOf(MaxIdle));
		poolConfig.setMaxWait(Duration.ofMillis(Long.valueOf(Long.valueOf(MaxWait))));
		poolConfig.setSoftMinEvictableIdleDuration(Duration.ofMillis(Long.valueOf(MinEvictableIdle)));
		poolConfig.setNumTestsPerEvictionRun(Integer.valueOf(NumTestsPerEvictionRun));
		poolConfig.setTimeBetweenEvictionRuns(Duration.ofMillis(Long.valueOf(TimeBetweenEvictionRunsMillis)));
		poolConfig.setBlockWhenExhausted(Boolean.valueOf(BlockWhenExhausted));
		
		sentinelPool = new JedisSentinelPool(RedisMaster, sentinels,poolConfig, RedisPassword);
	}
	
	private Jedis getJedis(){
		return getInstans().sentinelPool.getResource();
	}
	
	public String set(String key,String value){
		Jedis redis = null;
		String result = null;
		try {
			redis = getJedis();
			result = redis.set(key, value);

			return result;
		} catch (Exception e) {
			redis.close();
			e.printStackTrace();
		} finally {
			if (redis != null) {
				redis.close();
			}
		}
		return result;
	}
	
	public Long expire(String key,int seconds){
		Jedis redis = null;
		Long result = null;
		try {
			redis = getJedis();
			result = redis.expire(key, seconds);

			return result;
		} catch (Exception e) {  
			redis.close();
            e.printStackTrace();  
        } finally {
			if (redis != null) {
				redis.close();
			}
		}
		
		return result;
	}
	
	public Boolean exists(String key){
		Jedis redis = null;
		Boolean result = null;
		
		try {
			redis = getJedis();
			result = redis.exists(key);

			return result;
		} catch (Exception e) {  
			redis.close();
            e.printStackTrace();  
        } finally {
			if (redis != null) {
				redis.close();
			}
		}
		
		return result;
	}
	
	public String setex(String key,int seconds,String value){
		Jedis redis = null;
		String result = null;
		try {
			redis = getJedis();
			result = redis.setex(key, seconds, value);

			return result;
		} catch (Exception e) {
			redis.close();
			e.printStackTrace();
		} finally {
			if (redis != null) {
				redis.close();
			}
		}
		
		return result;
	}
	
	public String get(String key){
		
		Jedis redis = null;
		String result = null;
		try {
			redis = getJedis();
			result = redis.get(key);

			return result;
			
		} catch (Exception e) {
			redis.close();
			e.printStackTrace();
		} finally {
			if (redis != null) {
				redis.close();
			}
		}	
		
		return result;
	}
	
	public void closeJedis(Jedis jedis){
		if (jedis != null) {
			jedis.close();
		}     
	}
	
	private void closePool(){
		if (sentinelPool != null) {
			sentinelPool.close();
			sentinelPool.destroy();
		}     
	}
}
